// MineNGUI.cpp

#include "MineNGUI.h"
#include "Size.h"
#include <iostream>
#include <climits>

/**
* Constructor.
*
* @param grid a pointer to the model to be used.
*/
MineNGUI::MineNGUI( ObserverMineGrid *mines ) : MineUIInterface( mines ) { }

/**
 * Destructor.
 */
MineNGUI::~MineNGUI() { }

/**
* Returns an action according to the input.
*
* @return char the action on the MineGrid.
*/
char MineNGUI::getAction() const
{
	char t;
	std::cin >> t;
	return t;
}

/**
* Returns a point according to the input.
*
* @return Point a point to a mine.
*/
Point MineNGUI::getPoint() const
{
	int x;
	int y;

	while( !( std::cin >> x >> y ) )
	{
		clearInputBuffer();
		std::cout << "Invalid point, enter a new one: ";
	}

	Point p( x, y );
	return p;
}

/**
* Clear the input buffer.
*/
void MineNGUI::clearInputBuffer() const
{
	std::cin.clear();
	std::cin.ignore( INT_MAX, '\n' );
}

/**
 * Prints out the games ui.
 */
void MineNGUI::printUI() const
{
	printMines();
	printTime();
}

/**
* Update the observable.
*/
void MineNGUI::notify()
{
	printUI();
}

/**
 * Prints the mines.
 */
void MineNGUI::printMines() const
{
	Size k = mines->getGridSize();
	const int cols = k.getWidth();
	const int rows = k.getHeight();


	// The very top
	std::cout << "   ";

	for( int i = 0 ; i < cols ; ++i )
	{
		if( i < 10 )
			std::cout << " ";

		std::cout << "  " << i;
	}

	std::cout << "\n";

	// The grid

	for( int i = 0 ; i < rows ; ++i )
	{
		std::cout << "    ";

		// The "roof"
		if( i == 0 )
			for( int k = 0 ; k < cols ; ++k )
				std::cout << " ---";
      
		std::cout << "\n";

		if( i < 10 )
			std::cout << " ";

		std::cout << " " << i << " |";

		for( int j = 0 ; j < cols ; ++j )
		{
			Point p( j, i );
			bool isMine = mines->isMine( p );
			int s = mines->getMineState( p );
			std::cout << " ";

			// The square has been swept.
			if( mines->isSwept( p ) )
			{
				// Not a mine.
				if( !isMine )
					if( s != 0 )
						std::cout << s;
					else
						std::cout << ' ';
				// Is a mine.
				else
					std::cout << 'X';
			}
			// The square is flagged.
			else if( mines->isFlagged( p ) )
				std::cout << 'F';
			// The square is "untouched".
			else
				std::cout << '-';

			std::cout << "  ";//" |";
		}
      
		std::cout << "\n";
	}

	std::cout << "    ";

	// The "floor"
	for( int k = 0 ; k < cols ; ++k )
		std::cout << "    ";//" ---";

	std::cout << "\n";
}

/**
* Prints the current time of the game.
*
* @param clock the current time in the game
*/
void MineNGUI::printTime() const
{
	std::cout << "Time: "
		<< mines->getElapsedTime()
		<< "\n";
}
